#include "rtc_driver.h"
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>

void init_rtc_time(void)
{
    // 使用rtc,先给一个起始时间
    rtc_parameter_struct rtc_parameter;
    rtc_parameter.factor_asyn = 0x7f; // 异步分频系数,7位
    rtc_parameter.factor_syn = 2499;  // 同步分频系数,15位

    // 年月日
    rtc_parameter.year = 0x25;
    rtc_parameter.month = 0x04;
    rtc_parameter.day_of_week = 0x03;
    rtc_parameter.date = 0x23;
    rtc_parameter.hour = 0x19;
    rtc_parameter.minute = 0x20;
    rtc_parameter.second = 0x00;
    rtc_parameter.am_pm = RTC_PM;
    rtc_parameter.display_format = RTC_24HOUR;
    //
    rtc_init(&rtc_parameter);
}

void rtc_driver_init(void)
{
    // 电池管理加载
    // 外设时钟
    rcu_periph_clock_enable(RCU_PMU);
    pmu_backup_write_enable();

    // 重置备份域(不重置可能导致无法设置晶振,出现不走字的情况)
    // 如果使用备份域,则下边2行代码需要注释掉
    // rcu_bkp_reset_enable();
    // rcu_bkp_reset_disable();

    // if (RTC_BKP0 == 0xf234)
    // {
    //     // 说明不是第一次初始化，可以不用重新设置时间
    // }
    // else
    // { // 如果后备寄存器0 的值 不为 0XF234
    //     // 设置后备寄存器0的值为 0XF234，标记已经初始化过RTC
    //     RTC_BKP0 = 0xf234;
    //     // 初始化RTC时间
    //     RtcTimeConfig(0x23, 0x07, 0x12, 0x03, 0x12, 0x59, 0x50);
    // }

    // 设置时钟晶振LXTAL,低速外部时钟
    //  rcu_osci_on(RCU_LXTAL);
    //  rcu_osci_stab_wait(RCU_LXTAL);
    //  rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    // 设置时钟,使用内部IRC32k
    //  rcu_osci_on(RCU_IRC32K);
    //  rcu_osci_stab_wait(RCU_IRC32K);
    //  rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);

    // 设置时钟,使用外部高频晶振;等待晶振稳定
    rcu_osci_on(RCU_HXTAL);
    rcu_osci_stab_wait(RCU_HXTAL);
    //rcu_rtc_clock_config(RCU_RTCSRC_HXTAL);
		rcu_rtc_clock_config(RCU_RTCSRC_HXTAL_DIV_RTCDIV);
    // 选用外部高频晶振时,需要设置分频系数
    rcu_rtc_div_config(RCU_RTC_HXTAL_DIV25);

    // rtc功能加载
    rcu_periph_clock_enable(RCU_RTC);
    rtc_register_sync_wait();

    //
    init_rtc_time();
}

void rtc_print_time(void)
{
    rtc_parameter_struct rtc_parameter;
    rtc_current_time_get(&rtc_parameter);
    //
    uint16_t year = 2000 + READ_BCD(rtc_parameter.year);
    uint8_t month = READ_BCD(rtc_parameter.month);
    uint8_t day = READ_BCD(rtc_parameter.date);
    uint8_t hour = READ_BCD(rtc_parameter.hour);
    uint8_t minute = READ_BCD(rtc_parameter.minute);
    uint8_t second = READ_BCD(rtc_parameter.second);

    printf("rtc time: %04d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second);
}

void rtc_alarm_init(void)
{
    rtc_alarm_struct alarm;
    // 设置掩码:需要每分钟的特定秒都是闹钟,
    alarm.alarm_mask = RTC_ALARM_DATE_MASK | RTC_ALARM_HOUR_MASK | RTC_ALARM_MINUTE_MASK | RTC_ALARM_SECOND_MASK;
    //
    // 设置闹钟
    alarm.weekday_or_date = RTC_ALARM_DATE_MASK;
    alarm.alarm_day = 0x25;
    alarm.alarm_hour = 0x12;
    alarm.alarm_minute = 0x20;
    alarm.alarm_second = 0x00;
    alarm.am_pm = RTC_PM; // 下午

    rtc_alarm_config(RTC_ALARM0, &alarm);

    // 设置rtc中断
    nvic_irq_enable(RTC_Alarm_IRQn, 2, 0);
    // 启用中断
    rtc_interrupt_enable(RTC_INT_ALARM0);
    // 清理标记
    rtc_flag_clear(RTC_FLAG_ALRM0);
    // 开启rtc闹钟
    rtc_alarm_enable(RTC_ALARM0);

    // 外部中断
    exti_interrupt_flag_clear(EXTI_17);
    // 初始化外部中断开启
    exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    exti_interrupt_enable(EXTI_17);
}

// 中断
void RTC_Alarm_IRQHandler(void)
{
    // 清理状态,
    if (SET == rtc_flag_get(RTC_FLAG_ALRM0))
    {
        rtc_flag_clear(RTC_FLAG_ALRM0); // rtc的标志要清理
        exti_flag_clear(EXTI_17);        // 外部中断也要清理

        printf("起床\n");
    }
}

void rtc_driver_test(void)
{
    //systick_config(); 

    rtc_driver_init();

    rtc_alarm_init();

    while (1)
    {
        rtc_print_time();
        delay_1ms(1000);
    }
}
